#ifndef _DATRIE_H_
#define _DATRIE_H_

#define DICT_SIZE       (1<<19)		//[512K] dict alloced for words
#define DICT_WORD_LEN   (1<<6)		//[32] max word len
#define DICT_ITEM_LEN   (DICT_WORD_LEN << 4)	//[128] max item len 
#define DAT_BLOCK_SIZE  (1<<18)		//[128M] per alloc size
#define DAT_DEF_ROOT    (1)			//index of dat root
#define DAT_RES_MAX     (1<<4)		//[16] max result num
#define DAT_TAG_MAX		35			//[35] max tags num of each word
#define DAT_SCALE		256			//each index indicate a byte

enum	TAG_STATE		{TAG_POS=1, TAG_GRAM, TAG_NR, TAG_NS, TAG_TR, TAG_UNGRAM};

#define UNST2ARR(st, direct)	((st) * 2 + (direct))
enum	UNKNOWN_DIRECT	{UN_HEAD=0, UN_TAIL=1};
enum	UNKNOWN_TYPE	{
							UN_NONE=0,	//agent for head or tail
                            UN_NUM,	
                            UN_STR,
                            UN_TIME,
                            UN_PER,
                            UN_LOC,
                            UN_IT,
                            UN_PROP,
                            UN_ORG
						};
enum    UNKNOWN_ARRAY	{	
							UN_HEAD_NONE=0,	UN_TAIL_NONE,
							UN_HEAD_NUM,	UN_TAIL_NUM,
							UN_HEAD_STR, 	UN_TAIL_STR,
							UN_HEAD_TIME, 	UN_TAIL_TIME,
							UN_HEAD_PER,	UN_TAIL_PER,
							UN_HEAD_LOC,	UN_TAIL_LOC,
							UN_HEAD_IT,		UN_TAIL_IT,
							UN_HEAD_PROP,	UN_TAIL_PROP,
							UN_HEAD_ORG,	UN_TAIL_ORG
						};

/*|kind|    value   |*/
#define TAGK(id)	((id) >> 24)
#define TAGV(id)	((id) & 0x00FFFFFF)

#define END_FREQ	50610

#define HEADAT(p,i)	((i) == 0 ? NULL : (tag_head *)((p)->_da + (i)))
#define TAGAT(p,i)	((i) == 0 ? NULL : (tag_node *)((p)->_da + (i)))

typedef struct tag_node{
	unsigned int	id;
	int				freq;
	int				tagi;		//the next index of tag_node from root
} tag_node;

typedef struct tag_head{
	int				grami;		//pos, gram tag list
	int				rolei;		//nr, ns, tr tag list
	int				ungrami;	//ungram tag list
} tag_head;

typedef struct dict_item{
	char			word[DICT_WORD_LEN];
	unsigned short	len;				//to decide if the word is over
	struct tag_node	tags[DAT_TAG_MAX];	//tags, eg: NORMAL, BIGRAM, ROLE
} dict_item;

typedef struct dat_node{
	int				base;
	int				check;
	int				headi;		//the index of tag_head from root
} dat_node;

typedef struct dat_res_item{
	unsigned short	len;
	int				headi;		//the index of tag_head from root
} dat_res_item;

typedef struct dat_res{
	int				num;
	dat_res_item	item[DAT_RES_MAX];
} dat_res;

typedef struct dat{
	unsigned int	_volume;	//volume of double array
	unsigned int	_dt_size;	//size of dict table(real nodes)
	int				_root;		//root
	int				_base;		//next base position
	unsigned int	_size;		//the total of all nodes
	dat_node *		_da;		//double array
	dict_item *		_dt;		//dict table
} dat;

dat * dat_new();
int dat_free(dat * p);
int dat_fetch(const dat * p, const char * str, int depth, dat_res * res);
int dat_load(dat * p, const char * dat_path);
int dat_dump(dat * p, const char * dict_path, const char * dat_path);

#endif
